Kamailio 的两种计费机制

Kamailio 计费模块支持两种计费机制,实现对计费事件的写入:

  • 通过给 SIP 事务打上特殊标记,当该事务完成时将会写入计费事件(即,发送给上游的SIP响应代码大于或等于200)

  • 通过执行由 acc 模块导出的函数,由配置文件脚本配置,在任何时候都可以立即写入计费事件

下面,我们分别介绍这两种计费机制。

通过标识方式计费

默认配置文件使用基于标识的机制进行计费。这里的第一步是通过模块参数告诉 acc 标识的值。配置文件可以通过不同的参数支持每个存储后台。

  • log_flag- 指定用于标记事务以进行日志计费的标志。

  • db_flag- 指定用于标记数据库计费事务的标志。

  • radius_flag- 指定用于标记radius计费的标志。

当使用相同的标识时,系统会将计费事件写入多个后端。带此标识的事务仅在响应代码为200-299响应时进行计费。如果要在事务失败的情况下进行计费,必须设置另一个标志,该标志由参数failed_transaction_flag指定。

Kamailio 的默认配置文件会将计费记录间接写入syslog,并提供通过预处理器指令WITH_ACCDB启用将计费记录写入数据库的选项。相关的配置文件部分如下所示:

.... 
1.   #!define FLT_ACC 1
2.   #!define FLT_ACCMISSED 2
3.   #!define FLT_ACCFAILED 3
...
332.modparam("acc","log_flag", FLT_ACC)
...
1.   #!ifdef WITH_ACCDB 
340.modparam("acc","db_flag", FLT_ACC)

实际上,标记 1 用于记录成功的交易,标记 3 用于记录失败的交易(标记3不能单独使用,在这种情况下必须同时设置标记 1 )。

Flag 2 用于存储本地用户未接来电的详细信息,当呼出时是基于本地位置查询时才启用这个标识。

默认配置文件还提供了 MySQL 的 SQL 语句,用于创建accmissed_calls表的列。如果用户使用向导安装了 Siremis 界面配置的话,则不需要执行 SQL 语句,因为向导配置已经完成了 SQL 语句执行。接下来的是默认配置文件中的部分,解释了启用计费和在数据库表中创建额外列的操作。

# *** To enhance accounting execute:

# - enable mysql

# - define WITH_ACCDB

# - add following columns to database

#!ifdef ACCDB_COMMENT

ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';

ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';

ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';

#!endif

计费标记已设置为:

  • 初始INVITE请求(仅标记已接听的电话的详细信息,分别接收 200 ok 响应)。

  • BYE请求(标记为存储所有BYE事务的记录,包括那些没有得到 200 ok 响应的事务 - 在这种情况下,当一个呼叫人的网络连接突然中断时,来自另一方的BYE就不会得到 200 ok ,但用户仍然希望记录这些数据以便能够获取 CDR )。

  • 初始INVITE请求在用户位置查找后发送(这次标记为存储未接来电的详细信).

接下来是默认配置文件中相关的代码片段,其中重点标识了 setflag 的操作。

493.
494. # account only INVITEs 
495.if(is_method("INVITE")){
496.setflag(FLT_ACC); # 这里,do accounting 
497.}
498.
592.if(is_method("BYE")){
593.setflag(FLT_ACC); # 这里,do accounting ...
594.setflag(FLT_ACCFAILED); # 这里 ... even if the transaction fails
595.}
676.
677. # when routing via usrloc, log the missed calls also 
678.if(is_method("INVITE")){
679.setflag(FLT_ACCMISSED);// 这里
680.}

用户使用 Siremis 安装向导创建的 MYSQL 存储流程kamailio_cdrs(),可以将INVITE记录和BYE记录的详细信息合并到一个通话数据记录中。本章稍后将详细介绍此过程。

使用计费模块函数写入数据

对于每个存储后端来说,acc 模块都会导出一个函数来写入计费信息。考虑在本书中,我们仅专注于将计费信息写入 syslog 和数据库,因此相应的函数是:

  • acc_log_request(comment)

  • acc_db_request(comment,table)

参数comment是由配置文件设置的文本。它们以三位数字开头,则其值分为两部分,第一部分保存为 SIP 响应代码,第二部分保存为 SIP 响应原因文本。

table 参数表示要保存计费记录的数据库表的名称。该参数可以是动态字符串(包含的变量在运行时进行判断)。与使用标志时存储的详细信息相比,以表的形式存储时,这里部分值是不同:

  • 在执行时被记录时间戳,不再等待 SIP 响应

  • SIP 响应代码来自于函数参数(如果参数“注释以3位数字开头,后跟空格”)

  • SIP 响应原因文本来自于函数参数(当值匹配此模式时-参数“注释”除了前三个数字和后面的空格外的值)。

这些函数可用于 SIP 请求和响应,从已处理的 SIP 消息及其事务上下文中获取值。这里提供一个示例来说明通过调用计费函数来替换BYE的基于标识的计费机制:

592.  if (is_method("BYE")) {
593.  acc_log_request(210 Bye received”); # do accounting to syslog
594.  acc_db_request(210 Bye received”, “acc”); # do accounting to database
595.  }

当收到BYE时,记录被存储,因此不再担心无法得到响应。这些功能可用于写入同一事务中各种事件的计费记录。即使有许多 acc 模块参数可以自动记录早期媒体响应、ACK 或 CANCEL 请求,这些函数也可以让配置文件开发人员完全掌控何时执行它们。某些环境下,用户需要提供为计费或以统计为目的输出结果:

  • 在收到初始的INVITE时的数据

  • 在初始INVITE请求被发送时的数据

  • 当收到第一个临时响应时的数据

  • 收到铃声响应时的数据

例如,需要以上数据计算 PDD 呼叫方拨号后的延迟时间(PDD),PDD 是一个呼叫方在发送初始的INVITE之后和呼叫方收到对端响应(振铃音或者忙音响应)之间的一个时间差。